'use strict';

/**
 * an internal class to 
 */
class CheckResult {
  #result
  #checker
  constructor(itemName, checker) {
    this.itemName = itemName;
    this.#checker = checker;
    this.#result = false;
  }
  get checkResult() {
    return this.#result;
  }
  set checkResult(newResult) {
    this.#result = newResult;
  }
  async run() {
    this.#result = await this.#checker();
    return this.#result;
  }
};

function healthCheckUtils(opt) {
  const checkers = [];
  for (const [key, val] of Object.entries(opt)) {
    try {
      if (val === true) {
        const util = require(`./${key}HealthCheck`);
        if (util) {
          const cr = new CheckResult(key, util.getChecker());
          checkers.push(cr);
        }
      }
    } catch {
      // quiet fail
    }
  }
  return async(req, res) => {
    let result = true;
    for (let i = 0; i < checkers.length; i++) {
      result = result && (await checkers[i].run());
    }
    res.status(result ? 200 : 400).send(checkers.reduce((prev, cur) => {
      return Object.assign(prev, {
        [cur.itemName]: cur.checkResult,
      });
    }, {}));
  }
}

Object.assign(module.exports, {
  healthCheckUtils,
});
